﻿using Autofac.Core;
using AutoMapper;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using FlyingEyeClient.ApplicationServices.SignalRHubs;
using HandyControl.Controls;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System.Collections.ObjectModel;
using System.Configuration;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using WpfApp.Exceptions;
using WpfApp.MesServices;
using WpfApp.SaveInfos;
using WpfApp.Update;
using WpfApp.Views;
using MessageBox = HandyControl.Controls.MessageBox;

namespace WpfApp.ViewModels
{
    internal class MainWindowViewModel : ObservableObject
    {

        public MainWindowViewModel(
           SignalRClientService signalRClientService,
           IConfiguration configuration,
           ILogger<MainWindowViewModel> logger,
           IMapper mapper,
           IServiceProvider serviceProvider)
        {
            _mapper = mapper;
            _serviceProvider = serviceProvider;
            _logger = logger;
            var saveInfo = SaveInfo.Read<MainWindowSaveInfo>(MainWindowSaveInfo.MainWindowFile);
            ResourceId = saveInfo?.ResourceId ?? string.Empty;
            _configuration = configuration;
            _signalRClientService = signalRClientService;
            ConnectCommand = new RelayCommand<Button>(OnConnect);
            PositionList = new List<string>()
            {
                "呈现在左上角",
                "桌面顶部居中",
                "呈现在右上角",
                "隐藏提示窗口",
            };

            this.InitTopTipWindow();

            if (!string.IsNullOrWhiteSpace(saveInfo?.Message))
            {
                this.UpdateTopTip(saveInfo.Message);
            }

            CurrentApplication.NotifyApplicationMessage += CurrentApplication_NotifyApplicationMessage;

            OutputAppVersion();
            InboundCommand = new RelayCommand<Button>(OnInbound);
        }

        private async void OnInbound(Button? button)
        {
            if (string.IsNullOrWhiteSpace(this.MaterialBarcode))
            {
                this.LogMessage("请刷卡或输入物料条码", LogLevel.Warning);
                return;
            }

            var service = _serviceProvider.GetRequiredService<InBoundMesService>();
            var saveInfo = SaveInfo.Read<MesConfigSaveInfo>(MesConfigSaveInfo.MesConfigFile)
                ?? new MesConfigSaveInfo();
            var dto = _mapper.Map<StartRequestMessageDto>(saveInfo);
            dto.Sfc = this.MaterialBarcode.Trim();
            var isValidate = dto.Validate(out var message);

            if (isValidate)
            {
                if (button != null) button.IsEnabled = false;

                var result = await service.PostAsync(dto);

                if (result.Success)
                {
                    UpdateTopTip(result.Message);
                    this.LogMessage(result.Message ?? string.Empty, LogLevel.Information);
                }
                else
                {
                    this.LogMessage(result.Message ?? string.Empty, LogLevel.Error);
                }
                this.MaterialBarcode = string.Empty;
                if (button != null) button.IsEnabled = true;
            }
            else
            {
                this.LogMessage(message, LogLevel.Error);
            }
        }

        void OutputAppVersion()
        {
            Task.Run(async () =>
            {
                var service = _serviceProvider.GetRequiredService<UpdateService>();

                await Task.Delay(2000);
                try
                {
                    this.LogMessage($"当前软件版本 {CurrentApplication.Version}");
                    var info = await service.GetAppInformationAsync();
                    this.LogMessage($"最新软件版本 {info.Version}", LogLevel.Information);
                }
                catch (Exception ex)
                {
                    this.LogMessage($"获取软件版本信息错误", LogLevel.Error);
                    _logger.LogError(ex, "获取软件信息错误");
                }
            });
        }

        private void CurrentApplication_NotifyApplicationMessage(object? sender, ApplicationMessageEventArgs e)
        {
            Application.Current.Dispatcher.Invoke(() =>
            {
                if (e.Type == ApplicationMessageTypes.Info)
                    this.LogMessage(e.Message, LogLevel.Information);
                else if (e.Type == ApplicationMessageTypes.Error)
                    this.LogMessage(e.Message, LogLevel.Error);
                else if (e.Type == ApplicationMessageTypes.Warning)
                    this.LogMessage(e.Message, LogLevel.Warning);
            });
        }

        private bool _isClosed = false;

        public async void OnClose()
        {
            _isClosed = true;
            _topTipWindow?.Close();

            if (_isConnected)
            {
                await _signalRClientService.DisconnectAsync();
                _isConnected = false;
            }
        }

        private void InitTopTipWindow()
        {
            _topTipWindow = _serviceProvider.GetRequiredService<TopTipWindow>();
            _topTipWindow.Closed -= TopTipWindow_Closed;
            _topTipWindow.Closed += TopTipWindow_Closed;
            _topTipWindow.TipTextBlock.Text = "未进行极片分类";
            _topTipWindow.WindowBrush.Background = Brushes.Gray;
            _topTipWindow.Show();
        }

        private void TopTipWindow_Closed(object? sender, EventArgs e)
        {
            if (!_isClosed)
            {
                InitTopTipWindow();
                var saveInfo = SaveInfo.Read<MainWindowSaveInfo>(MainWindowSaveInfo.MainWindowFile);
                this.UpdateTopTip(saveInfo?.Message);
            }
        }

        private async void OnConnect(Button? ConnectionButton)
        {
            var host = _configuration["SignalRHost"];
            this.ResourceId = this.ResourceId.Trim();

            try
            {
                MainWindowSaveInfo saveInfo = SaveInfo.Read<MainWindowSaveInfo>(MainWindowSaveInfo.MainWindowFile)
                    ?? new MainWindowSaveInfo();

                if (saveInfo.ResourceId != this.ResourceId)
                {
                    saveInfo.ResourceId = this.ResourceId;
                    SaveInfo.Write(saveInfo, MainWindowSaveInfo.MainWindowFile);
                }

                if (!_isConnected)
                {
                    if (String.IsNullOrEmpty(host))
                    {
                        LogMessage("配置文件未设置服务器主机！", LogLevel.Error);
                        return;
                    }

                    if (String.IsNullOrEmpty(ResourceId))
                    {
                        LogMessage("设备资源号不能未空！", LogLevel.Error);
                        return;
                    }

                    if (ConnectionButton != null)
                    {
                        ConnectionButton.IsEnabled = false;
                    }

                    _signalRClientService.Connect -= OnSignalRConnect;
                    _signalRClientService.Connect += OnSignalRConnect;
                    _signalRClientService.ClassifyMeterial -= OnClassifyMeterial;
                    _signalRClientService.ClassifyMeterial += OnClassifyMeterial;
                    await _signalRClientService.ConnectAsync(host, this.ResourceId);
                    _isConnected = true;
                }
                else
                {
                    if (ConnectionButton != null)
                    {
                        ConnectionButton.IsEnabled = false;
                    }

                    await _signalRClientService.DisconnectAsync();
                    _isConnected = false;
                }
            }
            catch (UserFriendlyException ex)
            {
                MessageBox.Show(ex.Message, "软件错误");
            }
            finally
            {
                if (ConnectionButton != null)
                {
                    ConnectionButton.IsEnabled = true;

                    if (_isConnected)
                    {
                        ConnectionButton.Style = ConnectionButton.FindResource("ButtonDanger") as Style;
                        ConnectionButton.Content = "断开连接";
                    }
                    else
                    {
                        ConnectionButton.Style = ConnectionButton.FindResource("ButtonPrimary") as Style;
                        ConnectionButton.Content = "连接服务器";
                    }
                }
            }
        }

        private void OnClassifyMeterial(object? sender, FlyingEye.ApplicationContracts.ClassifyMeterialMessage e)
        {
            Application.Current.Dispatcher.InvokeAsync(new Action(() =>
            {
                UpdateTopTip(e.Message);
            }));
        }

        private void UpdateTopTip(string? message)
        {
            if (string.IsNullOrWhiteSpace(message))
            {
                LogMessage($"MES 极片信息为空，如果当前极片是阴极极片，请忽略该信息。", LogLevel.Warning);
            }
            else if (!message.Any(charItem => charItem > '0' && charItem < '9'))
            {
                LogMessage($"错误极片信息，{message}", LogLevel.Error);
            }
            else
            {
                LogMessage($"极片类别 {message}", LogLevel.Information);
                var charValue = message.FirstOrDefault(charItem => charItem > '0' && charItem < '9');

                (Brush brush, string message) value =

                charValue switch
                {
                    '1' => (Brushes.Red, "红色类别极片"),
                    '2' => (Brushes.Yellow, "黄色类别极片"),
                    '3' => (Brushes.White, "白色类别极片"),
                    _ => (Brushes.Gray, $"不能识别极片类型 {charValue} .")
                };

                MainWindowSaveInfo saveInfo = SaveInfo.Read<MainWindowSaveInfo>(MainWindowSaveInfo.MainWindowFile)
                    ?? new MainWindowSaveInfo();

                if (saveInfo.Message != message)
                {
                    saveInfo.Message = message;
                    SaveInfo.Write(saveInfo, MainWindowSaveInfo.MainWindowFile);
                }

                _topTipWindow?.Dispatcher.Invoke(() =>
                {
                    _topTipWindow.TipTextBlock.Text = value.message;
                    _topTipWindow.WindowBrush.Background = value.brush;
                });
            }
        }

        private void OnSignalRConnect(object? sender, FlyingEye.ApplicationContracts.SignalRHubs.ConnectionEventArgs e)
        {
            if (e.Status == FlyingEye.ApplicationContracts.SignalRHubs.SignalRConnectionStatus.Connected)
            {
                LogMessage("服务器连接成功！", LogLevel.Information);
            }
            else
            if (e.Status == FlyingEye.ApplicationContracts.SignalRHubs.SignalRConnectionStatus.Reconnecting)
            {
                LogMessage("服务器连接已断开，正在重新连接...", LogLevel.Error);
            }
            else
            if (e.Status == FlyingEye.ApplicationContracts.SignalRHubs.SignalRConnectionStatus.Reconnected)
            {
                LogMessage("服务器已重新连接成功！", LogLevel.Information);
            }
            else
            {
                LogMessage("已断开连接！", LogLevel.Information);
            }
        }

        private int _logCount = 0;

        public void LogMessage(string message, LogLevel level = LogLevel.None)
        {
            Application.Current.Dispatcher.Invoke(() =>
            {
                if (_logCount <= 60)
                {
                    _logCount++;
                }
                else
                {
                    Logs.RemoveAt(0);
                }
                LogBoxItem item = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "：" + message;
                item.Brush = GetMessageBrush(level);
                Logs.Add(item);
            });
        }

        private Brush GetMessageBrush(LogLevel logLevel = LogLevel.None)
        {
            return logLevel switch
            {
                LogLevel.Error => Brushes.Red,
                LogLevel.Information => Brushes.Green,
                LogLevel.Warning => Brushes.Orange,
                _ => Brushes.Black,
            };
        }

        private void ChangeTipWindowPosition(int selected)
        {
            switch (selected)
            {
                case 0:
                    _topTipWindow?.ShowTopLeft();
                    break;
                case 1:
                    _topTipWindow?.ShowTopCenter();
                    break;
                case 2:
                    _topTipWindow?.ShowTopRight();
                    break;
                default:
                    _topTipWindow?.HideTip();
                    break;
            };
        }

        private readonly ILogger<MainWindowViewModel> _logger;

        private readonly IServiceProvider _serviceProvider;

        public ObservableCollection<LogBoxItem> Logs { get; set; } = new ObservableCollection<LogBoxItem>();

        /// <summary>
        /// 设备资源号
        /// </summary>
        public string ResourceId { get; set; }

        private readonly SignalRClientService _signalRClientService;

        private readonly IConfiguration _configuration;

        /// <summary>
        /// 提示窗口坐标列表。
        /// </summary>
        public List<string> PositionList { get; set; }

        private TopTipWindow? _topTipWindow = null;

        public ICommand ConnectCommand { get; set; }


        private int _positionSelectedIndex;

        public int PositionSelectedIndex
        {
            get { return _positionSelectedIndex; }
            set
            {
                ChangeTipWindowPosition(value);
                _positionSelectedIndex = value;
            }
        }

        private bool _isConnected = false;

        public ICommand InboundCommand { get; set; }

        private readonly IMapper _mapper;

        private string? _materialBarcode;

        public string? MaterialBarcode
        {
            get => _materialBarcode;
            set => SetProperty(ref _materialBarcode, value);
        }

    }
}
